<?php
function cnupp_getErrMsg($ierr)
{
        switch($ierr)
        {
		case 0:     return "Success";
		case -1:    return "Network error";
		case -3:    return "System error";
		case -4:    return "New user id";
		case -5:    return "User does not have yuid key";
		case -6:    return "Max transfer length is exceeded";
		case -7:    return "Visit key is limitted";
		case -8:    return "Invalid domain";
		case -9:    return "User id does not exist";
		case -10:   return "Not login - call open() to login";
		case -11:   return "Invalid parameters";
		case -12:   return "user is not exist";
		case -13:   return "Invalid user id";
		case -15:   return "Key or value are too small";
		case -16:   return "Invalid char in key or value";
		case -17:   return "Server fatal error";
		case -18:   return "Network timeout";
		case -19:   return "User is already opened - close it before reopen";
		case -20:   return "User is already exist";
		case -21:   return "Key does not exist";
		case -22:   return "User no uuid, plase uuid func to recreate!";
		case -23:   return "the uuid is invalidate!";
		case -24:   return "can't to get uuid!";
		case -25:   return "input data is invalidate!";
		case -26:   return "response data is invalidate!";
		default:    return "Undefined error: $ierr";
	}
}

class Eagle{
	var $sock;
	var $domain;
	var $retry;
	function __construct($port = 4080, $dm ="y" ){
		$this->domain = $dm;
		$this->retry = 3;
	$this->sock = pfsockopen("localhost", $port, $errno, $errstr);
//	$this->sock = fsockopen("localhost", $port, $errno, $errstr);
		if (!$this->sock) 
			syslog("ERROR: $errno - $errstr");
	} 

	function __destruct() {
	} 

	function domethod($method, $userid, $kv){
        $arr = array();
		if(!is_array($kv))
		{
			$arr['_retcode'] = -25; 
			return $arr;
		}
		$hash = 1; // + yax_compute_hash($userid, 0, 255, YAX_HASH_TYPE_MAGIC);
		$input = "P".pack("I", $hash)."\001";
		$input .= "P".pack("I", $hash)."\001";
		$input .= pack("II", $method, strlen($this->domain)).$this->domain.pack("I", strlen($userid)).$userid.pack("I", sizeof($kv));
		foreach($kv as $k=>$v)
			if(!empty($k))
				$input .=pack("I", strlen($k)).$k.pack("I", strlen($v)).$v;
                fwrite($this->sock, $input);
     	        $readlen = $READ = 102400;
		$response = fread($this->sock, $READ);
		//var_dump($response);
		if(isset($response{7}))
		{
			$sub = substr($response, 0, 8);
			$unpacked = unpack('I2',$sub);         
			//echo "yes:";  var_dump($unpacked); 
			if(isset($unpacked['1']) && isset($unpacked['2']))
			{
				$arr['_retcode'] = $unpacked['2'];
				if($unpacked['2'] != 0)
					return $unpacked['2'];
				$idx = 8;
				$sub = substr($response, $idx , 4);
                if(!isset($sub{3}))
					return false;
				$unpacked = unpack('I',$sub);      
				//echo "items = "; var_dump($unpacked);
				$idx += 4;    
				$item = $unpacked['1'];
				for($j = 0; $j<$item ; $j++)
				{
					$str = substr($response, $idx, 4);
					if(!isset($str{3}))
						return false;

					$unpacked = unpack('Iint', $str);
					$idx += 4;
					$key = substr($response, $idx, $unpacked['int']);
			//		echo "key=$key\n";var_dump($unpacked);
					$idx += $unpacked['int'];
					$str = substr($response, $idx, 4);
					if(!isset($str{3}))
						return false;

					$unpacked = unpack('Iint', $str);
					$idx += 4;
					$val = substr($response, $idx, $unpacked['int']);
			//		echo "val =$val"; var_dump($unpacked);
					$idx += $unpacked['int'];
					$arr[$key] = $val;
				}
			}
		}
                else
                   $arr['_retcode'] = -26;
            return $arr;                
	}


	function open($userid, $kv = array(), $create = false){
		$ret = false;
		$try = 0;

		while($ret === false && $try< $this->retry)
		{
			if($create)        
				$ret = $this->domethod(11 /* CNUPP_OPEN2 */, $userid, $kv);
			else
				$ret= $this->domethod(10 /* CNUPP_OPEN1 */, $userid, $kv);
			$try++;
		}
		return $ret;
	}

	function read($userid, $kv = array()){
		$ret = false;
		$try = 0;
		while($ret === false && $try< $this->retry)
		{
			$ret = $this->domethod(2 /* CNUPP_READ */, $userid, $kv);
			$try++;
		}
		return $ret;
	}

	function write($userid, $kv = array()){
		$ret = false;
		$try = 0;
		while($ret === false && $try< $this->retry)
		{
			$ret = $this->domethod(3 /* CNUPP_WRITE */, $userid, $kv);
			$try++;
		}
		return $ret;

	}

	function create($userid, $kv = array()){
		$ret = false;
		$try = 0;
		while($ret === false && $try< $this->retry)
		{
			$ret = $this->domethod(12 /* CNUPP_CREATE */, $userid, $kv);
			$try++;
		}
		return $ret;
	}
	function atom($userid, $kv = array()){
		$ret = false;
		$try = 0;
		while($ret === false && $try< $this->retry)
		{
			$ret = $this->domethod(6 /* CNUPP_ATOM */, $userid, $kv);
			$try++;
		}
		return $ret;
	}
	function dump($userid){
		$ret = false;
		$try = 0;
		while($ret === false && $try< $this->retry)
		{
			$ret = $this->domethod(13 /* CNUPP_DUMP */, $userid, array());
			$try++;
		}
		return $ret;
	}
	
	function mopen($users, $kv){
		$ret = false;
		$try = 0;
		while($ret === false && $try< $this->retry)
		{
			$ret = $this->inner_mopen($users, $kv);
			$try++;
		}
		return $ret;
	}

	function inner_mopen($users, $kv){
        $arr = array();
		if(!is_array($kv) || !is_array($users))
		{
			$arr['_retcode'] = -25; 
			return $arr;
		
}
$userid = "";
foreach($users as $k=>$v)
{
	$userid = $k;
	break;
}

        $user_counts = sizeof($users);
 	$hash = 1 ; //+ yax_compute_hash($userid, 0, 255, YAX_HASH_TYPE_MAGIC);
        $input = "P".pack("I", $hash)."\001";
        $input .= "P".pack("I", $hash)."\001";
	$input .= pack("II", 14 /*CNUPP_ACT_MOPEN*/, strlen($this->domain)).$this->domain.pack("I", $user_counts);
		foreach($users as $k=>$v)
			$input .=pack("I", strlen($k)).$k;

        $arg_counts = sizeof($kv);
        $input .= pack("I", $arg_counts);
		foreach($kv as $k=>$v)
			$input .=pack("I", strlen($k)).$k;
        fwrite($this->sock, $input);
        $readlen = $READ = 102400;
		$response = fread($this->sock, $READ);
//echo strlen($response)."\n";
//		var_dump($response);
		if(isset($response{7}))
		{
			$sub = substr($response, 0, 8);
			$unpacked = unpack('I2',$sub);         
//			echo "yes:";  var_dump($unpacked); 
			if(isset($unpacked['1']) && isset($unpacked['2']))
			{
				$arr['_retcode'] = $unpacked['2'];
				if($unpacked['2'] != 0)
					return $arr;

				$idx = 8;
				$sub = substr($response, $idx , 4);
				if(!isset($sub{3}))
					return false;
				$unpacked = unpack('I',$sub);      
//				echo "user counts = "; var_dump($unpacked);
				$idx += 4;    
				$uitems = $unpacked['1'];
				if($uitems > $user_counts)
				{
					$arr['_retcode'] = -3;
					return $arr;
				}    
				for($j = 0; $j<$uitems ; $j++)
				{
					$sub = substr($response, $idx , 4);
					if(!isset($sub{3}))
						return false;
					$unpacked = unpack('I',$sub);  //user length    
					//					echo "items = "; var_dump($unpacked);
					$ulen = $unpacked['1'];
					$idx += 4;
					$user = substr($response, $idx, $ulen);
					$idx += $ulen;
					$sub = substr($response, $idx , 4);
					if(!isset($sub{3}))
						return false;
	
					$unpacked = unpack('I',$sub);      
					$idx += 4;
					$items = $unpacked['1'];
					//  echo "user = $user\n";
					if($items > $arg_counts)
					{
						$arr['_retcode'] = -3;
						return $arr;
					}    

					$ukv = array();
					for($t = 0; $t<$items ; $t++)
					{
						$str = substr($response, $idx, 4);
						$unpacked = unpack('Iint', $str);
						$idx += 4;
						$key = substr($response, $idx, $unpacked['int']);
						$idx += $unpacked['int'];
						$str = substr($response, $idx, 4);
						$unpacked = unpack('Iint', $str);
						$idx += 4;
						$val = substr($response, $idx, $unpacked['int']);
						$idx += $unpacked['int'];
						$ukv[$key] = $val;
					}
					$arr[$user] = $ukv;
				}
			}
		}
		else
			$arr['_retcode'] = -26;
		return $arr;                
	}
}


$obj = new Eagle(7080, 'y');
$ret = $obj->open("lengsh#ap", array('sex'=>'', 'age'=>''));
var_dump($ret);

?>
